package com.aplink.generic.adapter;

import android.content.Context;
import android.graphics.Bitmap;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Filter;
import android.widget.Filterable;
import android.widget.ImageView;
import android.widget.TextView;

import com.aplink.dellcommercial.util.BitmapUtis;
import com.aplink.generic.constant.ColumnType;
import com.aplink.generic.pojo.GenericObject;
import com.aplink.generic.pojo.xml.ColumnSetting;
import com.aplink.generic.util.AndroidUIParser;
import com.aplink.generic.util.FetchBitmapAysn;
import com.aplink.generic.util.Utility;

import java.util.ArrayList;
import java.util.Date;
import java.util.Locale;

public class GenericConfigAdapter extends BaseAdapter implements Filterable {

    private ArrayList<ColumnSetting> mColumnSettingList = new ArrayList<ColumnSetting>();

    private final Context mContext;
    private ArrayList<GenericObject> mGenericObjectList;
    private final String mLayoutSrc;
    private ArrayList<GenericObject> mDisplayResult;

    public GenericConfigAdapter() {
        this.mContext = null;
        this.mGenericObjectList = null;
        this.mColumnSettingList = null;
        this.mLayoutSrc = "";
    }

    /**
     * How to use this class, mAdapter = new
     * GenericConfigAdapter(getApplicationContext
     * (),genericObjectList,columnSettingList,"redeem_item_config"); Please
     * remember that each row in this list is plugged its tag with its own
     * object Therefore in detail page we just extract the object and parse as
     * you want
     *
     * @param mContext
     * @param objects
     * @param columnSettings
     * @param layoutsrc
     */
    public GenericConfigAdapter( Context mContext,
                                 ArrayList<GenericObject> objects,
                                 ArrayList<ColumnSetting> columnSettings, String layoutsrc ) {

        this.mContext = mContext;
        this.mGenericObjectList = objects;
        this.mDisplayResult = objects;
        this.mColumnSettingList = columnSettings;
        this.mLayoutSrc = layoutsrc;
    }

    @Override
    public int getCount() {
        return this.mDisplayResult.size();
    }

    @Override
    public Filter getFilter() {
        final Filter filter = new Filter() {

            @Override
            protected FilterResults performFiltering( CharSequence searchContent ) {
                final FilterResults results = new FilterResults(); // Holds the
                // results of a
                // filtering
                // operation in
                // values

                // here we parse constraint to get Search contain and search
                // fields

                final String[] parts = searchContent.toString().split( ";" );
                CharSequence constraint = parts[0]; // here is search content

                final ArrayList<String> searchFields = new ArrayList<String>();
                for ( int i = 1 ; i < parts.length ; i++ ) {
                    if ( parts[i].toString() != "" ) {
                        searchFields.add( parts[i].toString().trim() );
                    }
                }
                // new array list of genericObjects
                final ArrayList<GenericObject> FilteredArrList = new ArrayList<GenericObject>();

                if ( GenericConfigAdapter.this.mDisplayResult == null ) {
                    GenericConfigAdapter.this.mDisplayResult = new ArrayList<GenericObject>(
                            GenericConfigAdapter.this.mGenericObjectList ); // saves
                    // the
                    // original
                    // data
                    // in
                    // mGenericObjectList
                }

                /********
                 *
                 * If constraint(CharSequence that is received) is null returns
                 * the mGenericObjectList (Original) values else does the
                 * Filtering and returns FilteredArrList(Filtered)
                 *
                 ********/
                if ( ( constraint == null ) || ( constraint.length() == 0 ) ) {

                    // set the Original result to return
                    results.count = GenericConfigAdapter.this.mGenericObjectList
                            .size();
                    results.values = GenericConfigAdapter.this.mGenericObjectList;
                } else {
                    constraint = constraint.toString().toLowerCase(
                            Locale.getDefault() );
                    for ( int i = 0 ; i < GenericConfigAdapter.this.mGenericObjectList
                            .size() ; i++ ) {
                        final GenericObject genericObject = GenericConfigAdapter.this.mGenericObjectList
                                .get( i );
                        // boolean isInside = genericObject
                        // .checkContentInsideObject(constraint.toString().toLowerCase());
                        final boolean isInside = genericObject
                                .checkContentInsideObjectByAttributes(
                                        constraint.toString().toLowerCase(
                                                Locale.getDefault() ),
                                        searchFields );
                        if ( isInside == true ) {
                            FilteredArrList.add( genericObject );
                        }

                    }
                    // set the Filtered result to return
                    results.count = FilteredArrList.size();
                    results.values = FilteredArrList;
                }
                return results;
            }

            @SuppressWarnings("unchecked")
            @Override
            protected void publishResults( CharSequence constraint,
                                           FilterResults results ) {

                GenericConfigAdapter.this.mDisplayResult = (ArrayList<GenericObject>) results.values; // has
                // the
                // filtered
                // values
                GenericConfigAdapter.this.notifyDataSetChanged(); // notifies
                // the data
                // with new
                // filtered
                // values
            }
        };
        return filter;
    }

    @Override
    public Object getItem( int position ) {
        return position;
    }

    @Override
    public long getItemId( int position ) {
        return position;
    }

    public ArrayList<GenericObject> getDisplayResult() {
        return mDisplayResult;
    }

    public void setDisplayResult( ArrayList<GenericObject> displayResult ) {
        mDisplayResult = displayResult;
        mGenericObjectList = displayResult;
        notifyDataSetChanged();
    }

    @Override
    public View getView( int position, View convertView, ViewGroup parent ) {

        View row = convertView;

        if ( row == null ) {
            final LayoutInflater vi = (LayoutInflater) this.mContext
                    .getSystemService( Context.LAYOUT_INFLATER_SERVICE );
            // here we reflection to get Integer of Layout
            final int idLayout = AndroidUIParser
                    .getLayoutIdByName( this.mLayoutSrc );
            row = vi.inflate( idLayout, null );

            final ViewHolder viewHolder = new ViewHolder();

            for ( final ColumnSetting columnSetting : this.mColumnSettingList ) {
                final String controlName = columnSetting.getLinkMappingName();
                if ( ! controlName.isEmpty() ) {
                    final int idControl = AndroidUIParser
                            .getViewIdByName( controlName );
                    if ( idControl == AndroidUIParser.RESOURCE_NOT_FOUND ) {
                        continue;
                    }
                    final View view = row.findViewById( idControl );
                    view.setTag( columnSetting );
                    viewHolder.views.add( view );
                }
            }
            row.setTag( viewHolder );
        }
        final GenericObject object = this.mDisplayResult.get( position );
        if ( object == null ) {
            return null;
        }
        final ViewHolder holder = (ViewHolder) row.getTag();
        for ( final View view : holder.views ) {
            final ColumnSetting columnSetting = (ColumnSetting) view.getTag();
            ColumnType columnType = columnSetting.getColType();
            String format = columnSetting.getFormat();
            if ( view instanceof ImageView ) {
                final String content = object
                        .getContentFromAttributeName( columnSetting
                                .getMappingName() );
                handleImageView( (ImageView) view, columnSetting, content );
            } else if ( view instanceof TextView ) {
                String content = "";
                if ( columnType.equals( ColumnType.DateTime ) ) {
                    Date date = (Date) object
                            .getValueFromAttributeName( columnSetting
                                    .getMappingName() );
                    content = Utility.formatDateTime( date, format );
                } else if ( columnType.equals( ColumnType.Text ) ) {
                    content = (String) object
                            .getValueFromAttributeName( columnSetting
                                    .getMappingName() );
                }
                ( (TextView) view ).setText( content );
            }
        }
        return row;
    }

    private void handleImageView( final ImageView imageView,
                                  ColumnSetting columnSetting, final String imageFile ) {
        ColumnType columnType = columnSetting.getColType();
        if ( columnType.equals( ColumnType.Drawable ) ) {
            new FetchBitmapAysn( imageView, true, mContext.getResources() )
                    .execute( imageFile );
            imageView.post( new Runnable() {
                @Override
                public void run() {
                    int resId = AndroidUIParser.getDrawableIdByName( imageFile );
                    Bitmap bitmap = BitmapUtis
                            .decodeThumbnailBitmapFromResource(
                                    mContext.getResources(), resId );
                    imageView.setImageBitmap( bitmap );
                }
            } );
        } else if ( columnType.equals( ColumnType.Image ) ) {
            imageView.post( new Runnable() {
                @Override
                public void run() {
                    Bitmap bitmap = BitmapUtis
                            .decodeThumbnailBitmapFromFile( imageFile );
                    imageView.setImageBitmap( bitmap );
                }
            } );
        }
    }

    static class ViewHolder {
        public ArrayList<View> views;

        public ViewHolder() {
            this.views = new ArrayList<View>();
        }
    }
}
